package org.testis.services;

import org.testis.communicationmodule.services.CommunicationModuleTaskExecutor;
import org.testis.data.TestStepDataObject;
import org.testis.data.TestStepResultDataObject;
import org.testis.data.TestStepResultDataObjectDistributor;
import org.testis.data.TestStepResultType;
import org.testis.guiappsmodule.services.GuiAppsModuleTaskExecutor;
import org.testis.logging.AtofLogLevel;
import org.testis.logging.LogSenderService;
import org.testis.nicmodule.services.NicModuleTaskExecutor;
import org.testis.serialportmodule.services.SerialPortModuleTaskExecutor;
import org.testis.terminalapplicationmodule.services.TerminalApplicationModuleTaskExecutor;
import org.testis.utils.Networking;
import org.testis.webautomationmodule.services.WebAutomationModuleTaskExecutor;
import org.testis.wirelesssecuritymodule.services.WirelessSecurityModuleTaskExecutor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.LinkedList;

/**
 * A singleton class to get dataobject and send it to task executor. 
 * Basically if everything is on the way, then creates test step and executes it.
 * Before sending data to task executor , data is validated.
 * @author nurhat
 */
public class TestStepTaskCreator {

    private static TestStepTaskCreator m_testStepTaskCreator = null;

    private TestStepTaskCreator() {
    }

    /**
     * Get singleton TestStepTaskCreator object
     * @return
     */
    public static TestStepTaskCreator getInstance() {
        if (m_testStepTaskCreator == null) {
            m_testStepTaskCreator =
                    new TestStepTaskCreator();
        }
        return m_testStepTaskCreator;
    }

    /**
     * Gets related task executor singleton objet according to module type,
     * and send data to task executor for execution
     * @param dataObj
     */
    public void createTestStepTask(TestStepDataObject dataObj) {
        try {
            if (isValidDataObject(dataObj)) {
                String macAddress = null;
                if (dataObj.getMacAddress() != null) {
                    if (!dataObj.getMacAddress().
                            equals("")) {
                        macAddress = dataObj.getMacAddress();
                    }
                }
                if (Networking.isMacExists(macAddress)) {
                    try {
                        String computername = InetAddress.getLocalHost().getHostName();
                        String computerip = "";
                        ArrayList<String> ipList = Networking.getIps();
                        for (int i = 0; i < ipList.size(); i++) {
                            computerip = computerip + ":" + ipList.get(i);

                        }
                        LogSenderService.putMessageOnQueue("TestStepTaskCreator",
                                AtofLogLevel.INFO,
                                "Test is running on computer with name:"
                                + computername + " and with ips :" + computerip,
                                dataObj.getMessageId());
                    } catch (Exception e) {
                        LogSenderService.putMessageOnQueue("TestStepTaskCreator",
                                AtofLogLevel.INFO,
                                "Test is running on computer with mac:" + macAddress,
                                dataObj.getMessageId());
                    }

                    Class<?> cls = Class.forName("org.testis." + dataObj.getModuleType().toLowerCase()
                            + ".services." + dataObj.getModuleType()
                            + "TaskExecutor");
                    Method mainMethod =
                            cls.getMethod("getInstance",
                            new Class[]{});
                    AtofModuleTaskExecutor taskExecutor =
                            (AtofModuleTaskExecutor) mainMethod.invoke(null,
                            new Object[]{});
                    taskExecutor.executeTask(dataObj);
                }
            }
        } catch (Exception ex) {
            StringWriter sw = new StringWriter();
            ex.printStackTrace(new PrintWriter(sw));
            String stacktrace = sw.toString();
            LogSenderService.putMessageOnQueue("TestStepTaskCreator",
                    AtofLogLevel.ERROR,
                    "("
                    + stacktrace
                    + ")Given module type " + dataObj.getModuleType()
                    + " is not supported righ now at TestStepTaskCreator",
                    dataObj.getMessageId());
            TestStepResultDataObject res = new TestStepResultDataObject(
                    dataObj);
            res.setResultType(TestStepResultType.MISTAKE);
            TestStepResultDataObjectDistributor.getInstance().
                    distributeData(res);
        }
    }

    public void abortAllTasks(LinkedList<String> dataObj) {
        if (dataObj == null) {
            return;
        } else if (dataObj.size() == 0) {
            return;
        }
        for (int j = 0; j < dataObj.size(); j++) {
            WebAutomationModuleTaskExecutor.getInstance().cancelTask(dataObj.get(j));
            TerminalApplicationModuleTaskExecutor.getInstance().cancelTask(dataObj.get(j));
            WirelessSecurityModuleTaskExecutor.getInstance().cancelTask(dataObj.get(j));
            NicModuleTaskExecutor.getInstance().cancelTask(dataObj.get(j));
            CommunicationModuleTaskExecutor.getInstance().cancelTask(dataObj.get(j));
            GuiAppsModuleTaskExecutor.getInstance().cancelTask(dataObj.get(j));
            SerialPortModuleTaskExecutor.getInstance().cancelTask(dataObj.get(j));
        }
        /* ArrayList<String> macAdresses = Networking.getMacAddresses();
        boolean contains = false;
        for (int i = 0; i < macAdresses.size(); i++) {
        for (int j = 0; j < dataObj.size(); j++) {
        if (dataObj.get(j).equals(macAdresses.get(i))) {
        contains = true;
        break;
        }
        }
        if (contains) {
        break;
        }

        }
        if(!contains)
        return;
        AtofModule[] modules = AtofEnumaration.AtofModule.values();

        for (int i = 0; i < modules.length; i++) {
        try {
        AtofModule atofModule = modules[i];
        Class<?> cls =
        Class.forName("org.testis."
        + atofModule.name().toLowerCase() + ".services."
        + atofModule.name() + "TaskExecutor");
        if (cls != null) {
        try {
        Method mainMethod =
        cls.getMethod("getInstance",
        new Class[]{});
        AtofModuleTaskExecutor taskExecutor =
        (AtofModuleTaskExecutor) mainMethod.invoke(null,
        new Object[]{});
        taskExecutor.abortAllTasks(true);
        } catch (IllegalAccessException ex) {
        } catch (IllegalArgumentException ex) {
        } catch (InvocationTargetException ex) {
        } catch (NoSuchMethodException ex) {
        } catch (SecurityException ex) {
        }
        }
        } catch (ClassNotFoundException ex) {
        }
        }*/
    }

    /**
     * Checks validation of data
     * @param data
     * @return
     */
    private boolean isValidDataObject(TestStepDataObject data) {
        if (data == null) {
            LogSenderService.putMessageOnQueue("TestStepTaskCreator",
                    AtofLogLevel.ERROR,
                    "Data object  must not be null...",
                    data.getMessageId());
            return false;
        }

        return true;
    }
}
